package com.aleyn.router.inject

import android.content.ComponentCallbacks
import com.aleyn.router.inject.instance.Def
import com.aleyn.router.inject.instance.FactoryInstanceFactory
import com.aleyn.router.inject.instance.Kind
import com.aleyn.router.inject.instance.Parameters
import com.aleyn.router.inject.instance.SingleInstanceFactory
import com.aleyn.router.inject.instance.createDefinition
import com.aleyn.router.inject.qualifier.Qualifier
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass

/**
 * @author : Aleyn
 * @date : 2023/07/26 : 22:56
 *
 * 提供依赖注入相关的工具函数和 DSL。
 */

// 用于缓存 KClass 对应的全限定名，避免重复反射获取
private val classNames: MutableMap<KClass<*>, String> = ConcurrentHashMap()

/**
 * 获取 KClass 的全限定名，优先从缓存中读取。
 */
fun KClass<*>.getFullName(): String {
    return classNames[this] ?: saveCache()
}

/**
 * 将 KClass 的全限定名存入缓存。
 */
private fun KClass<*>.saveCache(): String {
    val name = this.java.name
    classNames[this] = name
    return name
}

/**
 * 创建参数列表的辅助函数。
 *
 * @param params 传递给实例构造函数的参数。
 * @return [Parameters] 实例。
 */
fun paramOf(vararg params: Any?) = Parameters(params.toMutableList())

/**
 * 定义一个单例（Singleton）依赖。
 *
 * @param T 要定义的实例类型。
 * @param qualifier 可选的限定符，用于区分同一类型的不同实例。
 * @param lazy 是否延迟初始化。如果为 false，将在调用 `createEagerInstances` 时立即创建。
 * @param definition 创建实例的 lambda 表达式。
 */
inline fun <reified T> lRouterSingle(
    qualifier: Qualifier? = null,
    lazy: Boolean = true,
    noinline definition: Def<T>
) {
    val def = createDefinition(Kind.SINGLETON, qualifier, definition)
    val factory = SingleInstanceFactory(def)
    Core.saveFactory(factory)
    if (!lazy) {
        Core.instanceRegistry.addEagerInstances(factory)
    }
}

/**
 * 定义一个工厂（Factory）依赖。
 * 每次请求都会创建一个新的实例。
 *
 * @param T 要定义的实例类型。
 * @param qualifier 可选的限定符。
 * @param definition 创建实例的 lambda 表达式。
 */
inline fun <reified T> lRouterFactory(
    qualifier: Qualifier? = null,
    noinline definition: Def<T>
) {
    val def = createDefinition(Kind.FACTORY, qualifier, definition)
    val factory = FactoryInstanceFactory(def)
    Core.saveFactory(factory)
}


/**
 * 为 Android 组件（如 Activity, Fragment）提供懒加载方式的依赖注入。
 *
 * @param T 要注入的实例类型。
 * @param qualifier 可选的限定符。
 * @param parameters 创建实例时需要的参数。
 * @param mode 懒加载的线程安全模式。
 * @return 一个 Lazy 委托，在首次访问时创建并返回实例。
 */
inline fun <reified T : Any> ComponentCallbacks.inject(
    qualifier: Qualifier? = null,
    parameters: Parameters? = null,
    mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
) = lazy(mode) { get<T>(qualifier, parameters) }

/**
 * 为 Android 组件提供直接获取实例的方式。
 *
 * @param T 要获取的实例类型。
 * @param qualifier 可选的限定符。
 * @param parameters 创建实例时需要的参数。
 * @return 实例。
 */
inline fun <reified T : Any> ComponentCallbacks.get(
    qualifier: Qualifier? = null,
    parameters: Parameters? = null,
): T {
    return Core.get(qualifier, parameters)
}
